package hh.asm;

import org.objectweb.asm.*;

public class CostDump implements Opcodes {

    public static void main(String[] args) throws Exception {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(52, ACC_PUBLIC + ACC_SUPER, "hh/asm/domain/Cost", null, "java/lang/Object", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, new String[]{"java/lang/Exception"});
            mv.visitParameter("args", 0);
            mv.visitCode();
            Label l0 = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(l0, l1, l2, "java/lang/InterruptedException");
            Label l3 = new Label();
            Label l4 = new Label();
            mv.visitTryCatchBlock(l0, l3, l4, null);
            Label l5 = new Label();
            mv.visitTryCatchBlock(l4, l5, l4, null);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
            mv.visitVarInsn(LSTORE, 1);
            mv.visitLdcInsn(Type.getType("Lhh/asm/domain/Cost;"));
            mv.visitInsn(DUP);
            mv.visitVarInsn(ASTORE, 3);
            mv.visitInsn(MONITORENTER);
            mv.visitLabel(l0);
            mv.visitLdcInsn(new Long(1000L));
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "sleep", "(J)V", false);
            mv.visitLabel(l1);
            Label l6 = new Label();
            mv.visitJumpInsn(GOTO, l6);
            mv.visitLabel(l2);
            mv.visitFrame(Opcodes.F_FULL, 3, new Object[]{"[Ljava/lang/String;", Opcodes.LONG, "java/lang/Object"}, 1, new Object[]{"java/lang/InterruptedException"});
            mv.visitVarInsn(ASTORE, 4);
            mv.visitVarInsn(ALOAD, 4);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/InterruptedException", "printStackTrace", "()V", false);
            mv.visitLabel(l6);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l3);
            Label l7 = new Label();
            mv.visitJumpInsn(GOTO, l7);
            mv.visitLabel(l4);
            mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/Throwable"});
            mv.visitVarInsn(ASTORE, 5);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l5);
            mv.visitVarInsn(ALOAD, 5);
            mv.visitInsn(ATHROW);
            mv.visitLabel(l7);
            mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
            mv.visitVarInsn(LSTORE, 3);
            mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitVarInsn(LLOAD, 3);
            mv.visitVarInsn(LLOAD, 1);
            mv.visitInsn(LSUB);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(J)V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(5, 6);
            mv.visitEnd();
        }
        cw.visitEnd();

        Class aClass = new MyClassLoader().defineClass("hh.asm.domain.Cost", cw.toByteArray());

        Object obj = aClass.newInstance();
        System.out.println(obj);
    }

}
